package com.plugin;

import com.util.StringUtil;
import org.mybatis.generator.api.GeneratedJavaFile;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.config.PropertyRegistry;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

/**
 * 描述：生成控制器代码
 * 作者：刘飞华
 * 日期：2024/7/24 13:52
 */
public class ControllerGenerator extends PluginAdapter {

    private final Properties properties;

    private String author;

    private String createTime;

    @Override
    public boolean validate(List<String> warnings) {
        return true;
    }

    public ControllerGenerator() {
        this.properties = new Properties();
    }

    public ControllerGenerator(Properties properties) {
        this.properties = properties;
    }


    @Override
    public void setProperties(Properties properties) {
        this.properties.putAll(properties);
        this.author = properties.getProperty("author");
        SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        this.createTime = dateFormatter.format(new Date());
    }

    /**
     * 可以生成自定义的文件
     */
    @Override
    public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) {
        List<GeneratedJavaFile> javaFiles = new ArrayList<>();
        javaFiles.add(genControllerJavaFile(introspectedTable));
        return javaFiles;
    }

    /**
     * 生成一个自定义文件
     */
    private GeneratedJavaFile genControllerJavaFile(IntrospectedTable introspectedTable) {
        String targetPackage = properties.getProperty("targetPackage");
        String[] split = introspectedTable.getBaseRecordType().split("\\.");
        String modelName = split[split.length - 1];
        String typeName = targetPackage + "." + modelName + "Controller";
        //类的完全限定名（决定生成的文件的目录接口）
        TopLevelClass c = new TopLevelClass(typeName);

        //设置注释
        c.addJavaDocLine("/**");
        String remarks = introspectedTable.getRemarks().replace("表","");
        c.addJavaDocLine(" * 描述: " + remarks);
        c.addJavaDocLine(" * 作者: " + author);
        c.addJavaDocLine(" * 日期: " + createTime);
        c.addJavaDocLine(" */");

        c.setVisibility(JavaVisibility.PUBLIC);

        String serviceName = StringUtil.firstCharToUpperCase(modelName) + "Service";
        Field f = new Field(serviceName,new FullyQualifiedJavaType(modelName + "Service"));
        f.setVisibility(JavaVisibility.PRIVATE);
        f.addAnnotation("@Autowired");
//        f.setName(serviceName);
//        f.setType(new FullyQualifiedJavaType(modelName + "Service"));
        c.addField(f);

        c.addAnnotation("@Tag(name = \"" + remarks + "\")");
        c.addAnnotation("@RestController");
        c.addAnnotation("@RequestMapping(\"/" + StringUtil.firstCharToUpperCase(modelName) + "\")");
        //导入的依赖包
        String basePackage = targetPackage.replace("controller", "");

        c.addImportedType(new FullyQualifiedJavaType("java.util.List"));
        c.addImportedType(new FullyQualifiedJavaType("io.swagger.v3.oas.annotations.Operation"));
        c.addImportedType(new FullyQualifiedJavaType("io.swagger.v3.oas.annotations.tags.Tag"));
        c.addImportedType(new FullyQualifiedJavaType("org.springframework.web.bind.annotation.*"));
        c.addImportedType(new FullyQualifiedJavaType("org.springframework.beans.factory.annotation.Autowired"));
        c.addImportedType(new FullyQualifiedJavaType("jakarta.validation.Valid"));
        c.addImportedType(new FullyQualifiedJavaType(basePackage + "service." + modelName + "Service"));
        c.addImportedType(new FullyQualifiedJavaType(basePackage + "vo.req.*"));
        c.addImportedType(new FullyQualifiedJavaType(basePackage + "vo.resp.*"));

        //构建一个编译单元
        GeneratedJavaFile generatedJavaFile = new GeneratedJavaFile(
                c,
                context.getJavaModelGeneratorConfiguration().getTargetProject(),
                context.getProperty(PropertyRegistry.CONTEXT_JAVA_FILE_ENCODING),
                context.getJavaFormatter());

        //1.添加方法
        Method add = new Method("save" + modelName);
        add.setName("save" + modelName);
        add.setVisibility(JavaVisibility.PUBLIC);
        add.setReturnType(FullyQualifiedJavaType.getIntInstance());
        Parameter parameter = new Parameter(new FullyQualifiedJavaType("Add" + modelName + "ReqVo"), "record");
        parameter.addAnnotation("@RequestBody @Valid");
        add.addParameter(parameter);
        add.addJavaDocLine("/**");
        add.addJavaDocLine(" * 添加" + remarks);
        add.addJavaDocLine(" *");
        add.addJavaDocLine(" * @param record 请求参数");
        add.addJavaDocLine(" * @return int");
        add.addJavaDocLine(" * @author " + author);
        add.addJavaDocLine(" * @date " + createTime);
        add.addJavaDocLine(" */");
        add.addAnnotation("@Operation(summary = \"添加" + remarks + "\")");
        add.addAnnotation("@PostMapping(\"/save" + modelName + "\")");

        add.addBodyLine("return " + serviceName + ".save" + modelName + "(record);");
        c.addMethod(add);

        //2.删除方法
        Method del = new Method("delete" + modelName);
        del.setName("delete" + modelName);
        del.setVisibility(JavaVisibility.PUBLIC);
        del.setReturnType(FullyQualifiedJavaType.getIntInstance());
        Parameter parameter1 = new Parameter(new FullyQualifiedJavaType("Delete" + modelName + "ReqVo"), "record");
        parameter1.addAnnotation("@RequestBody @Valid");
        del.addParameter(parameter1);
        del.addJavaDocLine("/**");
        del.addJavaDocLine(" * 删除" + remarks);
        del.addJavaDocLine(" *");
        del.addJavaDocLine(" * @param record 请求参数");
        del.addJavaDocLine(" * @return int");
        del.addJavaDocLine(" * @author " + author);
        del.addJavaDocLine(" * @date " + createTime);
        del.addJavaDocLine(" */");
        del.addAnnotation("@Operation(summary = \"删除" + remarks + "\")");
        del.addAnnotation("@PostMapping(\"/delete" + modelName + "\")");

        del.addBodyLine("return " + serviceName + ".delete" + modelName + "(record);");
        c.addMethod(del);

        //3.更新方法
        Method update = new Method("update" + modelName);
        update.setName("update" + modelName);
        update.setVisibility(JavaVisibility.PUBLIC);
        update.setReturnType(FullyQualifiedJavaType.getIntInstance());
        Parameter parameter2 = new Parameter(new FullyQualifiedJavaType("Update" + modelName + "ReqVo"), "record");
        parameter2.addAnnotation("@RequestBody @Valid");
        update.addParameter(parameter2);
        update.addJavaDocLine("/**");
        update.addJavaDocLine(" * 更新" + remarks);
        update.addJavaDocLine(" *");
        update.addJavaDocLine(" * @param record 请求参数");
        update.addJavaDocLine(" * @return int");
        update.addJavaDocLine(" * @author " + author);
        update.addJavaDocLine(" * @date " + createTime);
        update.addJavaDocLine(" */");
        update.addAnnotation("@Operation(summary = \"更新" + remarks + "\")");
        update.addAnnotation("@PostMapping(\"/update" + modelName + "\")");

        update.addBodyLine("return " + serviceName + ".update" + modelName + "(record);");
        c.addMethod(update);

        //4.更新状态方法
        Method updateStatus = new Method("update" + modelName + "Status");
        updateStatus.setName("update" + modelName + "Status");
        updateStatus.setVisibility(JavaVisibility.PUBLIC);
        updateStatus.setReturnType(FullyQualifiedJavaType.getIntInstance());
        Parameter parameter3 = new Parameter(new FullyQualifiedJavaType("Update" + modelName + "StatusReqVo"), "record");
        parameter3.addAnnotation("@RequestBody @Valid");
        updateStatus.addParameter(parameter3);
        updateStatus.addJavaDocLine("/**");
        updateStatus.addJavaDocLine(" * 更新" + remarks + "状态");
        updateStatus.addJavaDocLine(" *");
        updateStatus.addJavaDocLine(" * @param record 请求参数");
        updateStatus.addJavaDocLine(" * @return int");
        updateStatus.addJavaDocLine(" * @author " + author);
        updateStatus.addJavaDocLine(" * @date " + createTime);
        updateStatus.addJavaDocLine(" */");
        updateStatus.addAnnotation("@Operation(summary = \"更新" + remarks + "状态\")");
        updateStatus.addAnnotation("@PostMapping(\"/update" + modelName + "Status\")");

        updateStatus.addBodyLine("return " + serviceName + ".update" + modelName + "Status(record);");
        c.addMethod(updateStatus);

        //5.查询详情
        Method query = new Method("query" + modelName + "Detail");
        query.setName("query" + modelName + "Detail");
        query.setVisibility(JavaVisibility.PUBLIC);
        query.setReturnType(new FullyQualifiedJavaType("Query" + modelName + "DetailRespVo"));
        Parameter parameter4 = new Parameter(new FullyQualifiedJavaType("Query" + modelName + "DetailReqVo"), "record");
        parameter4.addAnnotation("@RequestBody @Valid");
        query.addParameter(parameter4);
        query.addJavaDocLine("/**");
        query.addJavaDocLine(" * 查询" + remarks + "详情");
        query.addJavaDocLine(" *");
        query.addJavaDocLine(" * @param record 请求参数");
        query.addJavaDocLine(" * @return Query" + modelName + "DetailRespVo");
        query.addJavaDocLine(" * @author " + author);
        query.addJavaDocLine(" * @date " + createTime);
        query.addJavaDocLine(" */");
        query.addAnnotation("@Operation(summary = \"查询" + remarks + "详情\")");
        query.addAnnotation("@PostMapping(\"/query" + modelName + "Detail\")");

        query.addBodyLine("return " + serviceName + ".query" + modelName + "Detail(record);");
        c.addMethod(query);

        //6.查询列表
        Method queryList = new Method("query" + modelName + "List");
        queryList.setName("query" + modelName + "List");
        queryList.setVisibility(JavaVisibility.PUBLIC);
        FullyQualifiedJavaType newArrayListInstance = FullyQualifiedJavaType.getNewListInstance();
        newArrayListInstance.addTypeArgument(new FullyQualifiedJavaType("Query" + modelName + "ListRespVo"));
        queryList.setReturnType(newArrayListInstance);
        Parameter parameter5 = new Parameter(new FullyQualifiedJavaType("Query" + modelName + "ListReqVo"), "record");
        parameter5.addAnnotation("@RequestBody @Valid");
        queryList.addParameter(parameter5);
        queryList.addJavaDocLine("/**");
        queryList.addJavaDocLine(" * 查询列表" + remarks + "列表");
        queryList.addJavaDocLine(" *");
        queryList.addJavaDocLine(" * @param record 请求参数");
        queryList.addJavaDocLine(" * @return List<Query" + modelName + "ListRespVo>");
        queryList.addJavaDocLine(" * @author " + author);
        queryList.addJavaDocLine(" * @date " + createTime);
        queryList.addJavaDocLine(" */");
        queryList.addAnnotation("@Operation(summary = \"查询" + remarks + "列表\")");
        queryList.addAnnotation("@PostMapping(\"/query" + modelName + "List\")");

        queryList.addBodyLine("return " + serviceName + ".query" + modelName + "List(record);");
        c.addMethod(queryList);

        return generatedJavaFile;
    }
}
